﻿using Library.Common.Model;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Library.Common.Document
{
    /// <summary>
    /// 文件帮助类
    /// </summary>
    public class FileHelper
    {

        #region 与Api.FilesManage服务相关

        /// <summary>
        /// 保存byte[]文件并返回路径
        /// </summary>
        /// <param name="filebyte">文件二进制</param>
        /// <param name="basepath">文件基础文件夹</param>
        /// <param name="tempPath">文件临时文件夹</param>
        /// <param name="fileName">文件名称</param>
        /// <returns></returns>
        public static string SaveFile(byte[] filebyte, string basepath, string tempPath, string fileName)
        {
            string result = string.Empty;
            try
            {
                string rootFileName = Directory.GetCurrentDirectory();
                //虚拟路径
                string path = tempPath != "" && tempPath != null ? $"{rootFileName}/Files/{basepath}/{tempPath}" : $"{rootFileName}/Files/{basepath}";

                var createResult = CreateDirectory(path);
                if (createResult)
                {
                    //物理路径
                    string filepath = path + "/" + fileName;

                    if (FileExists(filepath))
                    {
                        DeleteFile(filepath);
                    }
                    using (FileStream fs = new FileStream(filepath, FileMode.CreateNew))
                    {
                        fs.Write(filebyte, 0, filebyte.Length);
                        fs.Dispose();
                        if (string.IsNullOrEmpty(tempPath))
                        {
                            result = $"/src/{basepath}/" + fileName; ;
                        }
                        else
                        {
                            result = $"/src/{basepath}/" + tempPath + "/" + fileName; ;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return result;
        }

        /// <summary>
        /// 合并文件
        /// </summary>
        /// <param name="basepath">基础文件夹名称</param>
        /// <param name="tempPath">临时文件夹名称</param>
        /// <param name="type">文件格式</param>
        /// <returns></returns>
        public static FilesInfo FileMerge(string basepath, string tempPath, string type)
        {
            FilesInfo fileInfo = new FilesInfo();
            try
            {
                string rootFileName = Directory.GetCurrentDirectory();

                DateTime dt = DateTime.Now;
                string fileName = string.Format("{0:yyMMdd}", dt).ToString() + Guid.NewGuid().ToString().Replace("-", "").ToUpper() + "." + type;

                var finalFilePath = $"{rootFileName}/Files/{basepath}/{fileName}";//最终的文件名
                var tempFilePath = $"{rootFileName}/Files/{basepath}/{tempPath}";//临时的文件夹

                var files = Directory.GetFiles(tempFilePath);//获得下面的所有文件
                using (var fs = new FileStream(finalFilePath, FileMode.Create))
                {
                    double byteLength = 0;
                    foreach (var part in files.OrderBy(x => x.Length).ThenBy(x => x))
                    {
                        var bytes = File.ReadAllBytes(part);
                        fs.WriteAsync(bytes, 0, bytes.Length);
                        byteLength += bytes.Length;
                        bytes = null;
                        File.Delete(part);//删除分块

                    }
                    Directory.Delete(tempFilePath);//删除文件夹

                    fileInfo.Path = $"/src/{basepath}/" + fileName;
                    fileInfo.Name = fileName;
                    // image  video  voice file
                    if ("gif,jpg,jpeg,bmp,png".IndexOf(type) > -1)
                    {
                        fileInfo.MediaType = "image";
                    }
                    else if ("doc,docx,xls,xlsx,ppt,pptx,pdf,tx".IndexOf(type) > -1)
                    {
                        fileInfo.MediaType = "file";
                    }
                    else if ("mp4,avi".IndexOf(type) > -1)
                    {
                        fileInfo.MediaType = "video";
                    }
                    else
                    {
                        fileInfo.MediaType = "file";
                    }
                    fileInfo.MediaSubType = type;
                    fileInfo.Size = byteLength / 1024;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return fileInfo;
        }

        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static bool FileRemove(string basepath, string fileName)
        {
            bool result = false;
            try
            {
                string rootFileName = Directory.GetCurrentDirectory();
                var finalFilePath = string.Empty;
                if (string.IsNullOrEmpty(basepath))
                {
                    finalFilePath = $"{rootFileName}/Files/{fileName}";//最终的文件名
                }
                else
                {
                    finalFilePath = $"{rootFileName}/Files/{basepath}/{fileName}";//最终的文件名
                }
                if (FileExists(finalFilePath))
                {
                    File.SetAttributes(finalFilePath, FileAttributes.Normal);
                    File.Delete(finalFilePath);
                }
                result = true;
            }
            catch (Exception e)
            {
                throw e;
            }
            return result;
        }

        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static bool FileRemove(string fileName)
        {
            bool result = false;
            try
            {
                string rootFileName = Directory.GetCurrentDirectory();
                var finalFilePath = $"{rootFileName}/Files/{fileName}";//最终的文件名
                if (FileExists(finalFilePath))
                {
                    File.SetAttributes(finalFilePath, FileAttributes.Normal);
                    File.Delete(finalFilePath);
                }
                result = true;
            }
            catch (Exception e)
            {
                throw e;
            }
            return result;
        }

        /// <summary>
        ///判断文件是否存在
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static bool ExistFile(string basepath, string fileName)
        {
            bool result = false;
            try
            {
                string rootFileName = Directory.GetCurrentDirectory();
                var finalFilePath = $"{rootFileName}/Files/{basepath}/{fileName}";//最终的文件名
                result = FileExists(finalFilePath);
            }
            catch (Exception e)
            {
                throw e;
            }
            return result;
        }

        #endregion

        #region 切片文件操作

        /// <summary>
        /// 保存切片byte[]文件并返回路径
        /// </summary>
        /// <param name="filebyte">文件二进制</param>
        /// <param name="filePath">文件基础文件夹</param>
        /// <param name="tempPath">文件临时文件夹</param>
        /// <param name="fileName">文件名称</param>
        /// <returns></returns>
        public static string SaveSlicingFile(byte[] filebyte, string filePath, string tempPath, string fileName)
        {
            string result = string.Empty;
            try
            {
                string rootFileName = Directory.GetCurrentDirectory();
                //虚拟路径
                string path = tempPath != "" && tempPath != null ? $"{filePath}/{tempPath}" : filePath;
                var createResult = CreateDirectory(path);
                if (createResult)
                {
                    //物理路径
                    string filepath = path + "/" + fileName;
                    if (FileExists(filepath))
                    {
                        DeleteFile(filepath);
                    }
                    using (FileStream fs = new FileStream(filepath, FileMode.CreateNew))
                    {
                        fs.Write(filebyte, 0, filebyte.Length);
                        fs.Dispose();
                        result = $"{path}/" + fileName;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return result;
        }

        /// <summary>
        /// 合并切片文件
        /// </summary>
        /// <param name="filePath">基础文件夹名称</param>
        /// <param name="tempPath">临时文件夹名称</param>
        /// <param name="type">文件格式</param>
        /// <returns></returns>
        public static FilesInfo MergeSlicingFile(string filePath, string tempPath, string type)
        {
            FilesInfo fileInfo = new FilesInfo();
            try
            {
                DateTime dt = DateTime.Now;
                string fileName = Guid.NewGuid().ToString().Replace("-", "").ToUpper() + "." + type;

                var finalFilePath = $"{filePath}/{fileName}";//最终的文件名
                var tempFilePath = $"{filePath}/{tempPath}";//临时的文件夹

                var files = Directory.GetFiles(tempFilePath);//获得下面的所有文件
                using (var fs = new FileStream(finalFilePath, FileMode.Create))
                {
                    double byteLength = 0;
                    foreach (var part in files.OrderBy(x => x.Length).ThenBy(x => x))
                    {
                        var bytes = File.ReadAllBytes(part);
                        fs.WriteAsync(bytes, 0, bytes.Length);
                        byteLength += bytes.Length;
                        bytes = null;
                        File.Delete(part);//删除分块
                    }
                    Directory.Delete(tempFilePath);//删除文件夹
                    fileInfo.Path = filePath;
                    fileInfo.Name = fileName;
                    fileInfo.MediaType = type;
                    fileInfo.MediaSubType = type;
                    fileInfo.Size = byteLength / 1024;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return fileInfo;
        }

        #endregion

        /// <summary>
        /// 保存文件信息
        /// </summary>
        /// <param name="file"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static string SaveFile(IFormFile file, string filePath)
        {
            string result = string.Empty;
            try
            {
                var createResult = CreateDirectory(filePath);
                if (createResult)
                {
                    var fileName = file.FileName;
                    //物理路径
                    string filepath = filePath + "/" + fileName;

                    if (FileExists(filepath))
                    {
                        DeleteFile(filepath);
                    }
                    using (FileStream fs = new FileStream(filepath, FileMode.CreateNew))
                    {
                        file.CopyTo(fs);
                        fs.Flush();
                        result = filepath;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return result;
        }


        /// <summary>
        /// 根据文件路径读取文件内容
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <returns></returns>
        public static string ReadFileByPath(string path)
        {
            using (StreamReader sr = new StreamReader(path))
            {
                string result = sr.ReadToEnd();
                sr.Close();
                sr.Dispose();
                return result;
            }
        }

        /// <summary>
        /// 检测目录是否存在
        /// </summary>
        /// <param name="fullpath"></param>
        /// <returns></returns>
        public static bool DirectoryExists(string fullpath)
        {
            bool result = false;
            try
            {
                result = Directory.Exists(RepairPath(fullpath));
            }
            catch (Exception e)
            {
                throw e;
            }
            return result;
        }

        /// <summary>
        /// 检测文件是否存在
        /// </summary>
        /// <param name="fullpath"></param>
        /// <returns></returns>
        public static bool FileExists(string fullpath)
        {
            bool result = false;
            try
            {
                result = System.IO.File.Exists(RepairFileName(fullpath));
            }
            catch (Exception e)
            {
                throw e;
            }
            return result;
        }

        /// <summary>
        /// 创建目录
        /// </summary>
        /// <param name="fullpath"></param>
        /// <returns></returns>
        public static bool CreateDirectory(string fullpath)
        {
            bool result = false;
            if (string.IsNullOrEmpty(fullpath))
            {
                return result;
            }

            fullpath = fullpath.Trim();
            if (string.IsNullOrEmpty(fullpath))
            {
                return result;
            }
            if (!DirectoryExists(fullpath))
            {
                string sParent = ExtractPathParent(fullpath);
                if (CreateDirectory(sParent))
                {// 创建目录成功
                    try
                    {
                        Directory.CreateDirectory(fullpath);
                        result = true;
                    }
                    catch (Exception e)
                    {
                        throw e;
                    }
                }
            }
            else
            {
                result = true;
            }
            return result;
        }

        /// <summary>
        /// 删除目录,但不允许删除要盘符
        /// </summary>
        /// <param name="fullpath"></param>
        /// <returns></returns>
        public static bool EraseDirectory(string fullpath)
        {
            bool result = false;
            bool bHasError = false;
            try
            {
                if (fullpath != null)
                {
                    fullpath = RepairPath(fullpath);
                    if (DirectoryExists(fullpath))
                    {
                        if (String.Compare(fullpath.Substring(fullpath.Length - 2, 2), ":\\", true) != 0)
                        {// 不是根目录

                            // 删除子目录
                            List<string> directories = GetDirectories(fullpath);
                            if (!bHasError)
                            {
                                foreach (string dirName in directories)
                                {// 删除子目录
                                    if (!EraseDirectory(dirName))
                                    {
                                        bHasError = true;
                                        break;
                                    }
                                }
                            }

                            // 删除当前目录中的文件
                            List<string> files = GetFiles(fullpath);
                            foreach (string filename in files)
                            {
                                try
                                {
                                    System.IO.File.Delete(filename);
                                }
                                catch
                                {
                                    bHasError = true;
                                }
                            }

                            // 删除指定的目录
                            if (!bHasError)
                            {
                                try
                                {
                                    Directory.Delete(fullpath);
                                }
                                catch
                                {
                                    bHasError = true;
                                }
                            }

                            result = !bHasError;
                        }
                        else
                        {
                            result = false;
                        }
                    }
                    else
                    {
                        result = true;
                    }
                }
                else
                {
                    result = true;
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            return result;
        }

        /// <summary>
        /// 获取子目录
        /// </summary>
        /// <param name="fullpath"></param>
        /// <returns></returns>
        public static List<string> GetDirectories(string fullpath)
        {
            List<string> result = new List<string>();
            try
            {
                if (DirectoryExists(RepairPath(fullpath)))
                {
                    string[] list = Directory.GetDirectories(fullpath);
                    foreach (string name in list)
                    {
                        result.Add(name);
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            return result;
        }

        /// <summary>
        /// 查询文件列表
        /// </summary>
        /// <param name="fullpath"></param>
        /// <returns></returns>
        public static List<string> GetFiles(string fullpath)
        {
            List<string> result = new List<string>();
            try
            {
                if (DirectoryExists(RepairPath(fullpath)))
                {
                    string[] list = Directory.GetFiles(fullpath);
                    foreach (string name in list)
                    {
                        result.Add(name);
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            return result;
        }

        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static bool DeleteFile(string filename)
        {
            bool result = false;
            try
            {
                filename = RepairFileName(filename);
                if (FileExists(filename))
                {
                    System.IO.File.SetAttributes(filename, FileAttributes.Normal);
                    System.IO.File.Delete(filename);
                }
                result = true;
            }
            catch (Exception e)
            {
                throw e;
            }
            return result;
        }

        /// <summary>
        /// 分隔出上级目录
        /// </summary>
        /// <param name="fullpath"></param>
        /// <returns></returns>
        public static string ExtractPathParent(string fullpath)
        {
            if (string.IsNullOrEmpty(fullpath))
            {
                return "";
            }

            fullpath = fullpath.Trim();
            if (string.IsNullOrEmpty(fullpath))
            {
                return "";
            }

            if (fullpath[fullpath.Length - 1] == '\\')
            {
                fullpath = fullpath.Substring(0, fullpath.Length - 1);
            }
            return ExtractFilePath(fullpath);
        }

        /// <summary>
        /// 从完整路径中,分解出目录
        /// </summary>
        /// <param name="fullpath"></param>
        /// <returns></returns>
        public static string ExtractFilePath(string fullpath)
        {
            if (string.IsNullOrEmpty(fullpath))
            {
                return "";
            }

            fullpath = fullpath.Trim();
            if (string.IsNullOrEmpty(fullpath))
            {
                return "";
            }

            char[] arrF = fullpath.Trim().ToCharArray();
            int ipos = -1;
            for (int i = arrF.Length - 1; i >= 0; i--)
            {
                if (arrF[i] == '\\')
                {
                    break;
                }
                else
                {
                    ipos = i;
                }
            }

            if (ipos == -1)
            {
                return "";
            }

            StringBuilder strB = new StringBuilder();
            for (int i = 0; i < ipos; i++)
            {
                strB.Append(arrF[i]);
            }
            return strB.ToString();
        }

        /// <summary>
        /// 处理目录中的反斜线
        /// </summary>
        /// <param name="fullpath"></param>
        /// <returns></returns>
        public static string RepairPath(string fullpath)
        {
            if (string.IsNullOrEmpty(fullpath))
            {
                return "";
            }

            fullpath = fullpath.Trim();
            if (string.IsNullOrEmpty(fullpath))
            {
                return "";
            }

            StringBuilder result = new StringBuilder();
            string[] arrF = fullpath.Split('\\');
            for (int i = 0; i < arrF.Length; i++)
            {
                string sline = arrF[i];
                if (string.IsNullOrEmpty(sline))
                {
                    continue;
                }
                else if (string.IsNullOrEmpty(sline.Trim()))
                {
                    continue;
                }
                else
                {
                    result.Append(sline.Trim());
                    result.Append('\\');
                }
            }
            return result.ToString();
        }

        /// <summary>
        /// 处理文件名中的反斜线
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static string RepairFileName(string filename)
        {
            if (string.IsNullOrEmpty(filename))
            {
                return "";
            }

            filename = filename.Trim();
            if (string.IsNullOrEmpty(filename))
            {
                return "";
            }

            StringBuilder result = new StringBuilder();
            string[] arrF = filename.Split('\\');
            for (int i = 0; i < arrF.Length; i++)
            {
                string sline = arrF[i];
                if (string.IsNullOrEmpty(sline))
                {
                    continue;
                }
                else if (string.IsNullOrEmpty(sline.Trim()))
                {
                    continue;
                }
                else
                {
                    if (result.Length > 0)
                    {
                        result.Append('\\');
                    }
                    result.Append(sline.Trim());
                }
            }
            return result.ToString();
        }

        /// <summary>   
        /// 重命名文件夹内的所有子文件夹   
        /// </summary>   
        /// <param name="directoryName">文件夹名称</param>   
        /// <param name="newDirectoryName">新子文件夹名称格式字符串</param>   
        public static void RenameDirectories(string directoryName, string newDirectoryName)
        {
            int i = 1;
            string[] sDirectories = Directory.GetDirectories(directoryName);
            foreach (string sDirectory in sDirectories)
            {
                string sDirectoryName = Path.GetFileName(sDirectory);
                string sNewDirectoryName = string.Format(newDirectoryName, i++);
                string sNewDirectory = Path.Combine(directoryName, sNewDirectoryName);
                Directory.Move(sDirectory, sNewDirectory);
            }
        }

        /// <summary>
        /// 重命名文件夹内的所有文件名称【前提是文件处理格式，名称可以一致】
        /// </summary>
        /// <param name="directoryName"></param>
        /// <param name="newName"></param>
        public static void RenameFiles(string directoryName, string newName)
        {
            DirectoryInfo folder = new DirectoryInfo(directoryName);
            foreach (FileInfo file in folder.GetFiles())
            {
                file.MoveTo($"{directoryName}\\{newName}.{file.Name.Split('.')[1]}");
            }
        }
    }
}
